package com.baidu.music;

import java.io.IOException;
import java.lang.ref.WeakReference;

import com.baidu.music.IMediaPlaybackService;
import com.baidu.utils.Logger;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;

public class MediaPlaybackService extends Service {
	
    private static final int TRACK_ENDED = 1;
    private static final int RELEASE_WAKELOCK = 2;
    private static final int SERVER_DIED = 3;
    private static final int FADEIN = 4;
    private static final int MAX_HISTORY_SIZE = 100;
    
    public static final String ASYNC_OPEN_COMPLETE = "com.android.music.asyncopencomplete";
    public static final String PLAYSTATE_CHANGED = "com.android.music.playstatechanged";
    
	private MultiPlayer mPlayer;
    private String mFileToPlay;
	private WakeLock mWakeLock;
    private boolean mServiceInUse = false;
    private boolean mIsSupposedToBePlaying = false;
    	public void openFile(String path) {
            synchronized (this) {
                if (path == null) {
                    return;
                }
            }
            mFileToPlay = path;
            mPlayer.setDataSource(mFileToPlay);
    	}
		public void play() {
			if (mPlayer.isInitialized()) {
				mPlayer.start();
	            if (!mIsSupposedToBePlaying) {
	                mIsSupposedToBePlaying = true;
	                notifyChange(PLAYSTATE_CHANGED);
	            }
			}
		}


		public void pause() {
	        synchronized(this) {
	            if (isPlaying()) {
	                mPlayer.pause();
	                mIsSupposedToBePlaying = false;
	                notifyChange(PLAYSTATE_CHANGED);
	            }
	        }
		}


		public void stop() {
	        if (mPlayer.isInitialized()) {
	            mPlayer.stop();
	        }
	        mFileToPlay = null;
	        mIsSupposedToBePlaying = false;
		}

	    public long duration() {
	        if (mPlayer.isInitialized()) {
	            return mPlayer.duration();
	        }
	        return -1;
	    }

	    public long position() {
	        if (mPlayer.isInitialized()) {
	            return mPlayer.position();
	        }
	        return -1;
	    }

	    public long seek(long pos) {
	        if (mPlayer.isInitialized()) {
	            if (pos < 0) pos = 0;
	            if (pos > mPlayer.duration()) pos = mPlayer.duration();
	            return mPlayer.seek(pos);
	        }
	        return -1;
	    }

	    public void setRepeatMode(int repeatmode) {
	        synchronized(this) {
	            //mRepeatMode = repeatmode;
	            //saveQueue(false);
	        }
	    }
	    
	    /**
	     * Returns the path of the currently playing file, or null if
	     * no file is currently playing.
	     */
	    public String getPath() {
	        return mFileToPlay;
	    }

	    public boolean isPlaying() {
	    	return mIsSupposedToBePlaying;
	    }
	public void onCreate() {
		super.onCreate();
		Logger.i("MediaPlaybackService onCreate()");
        mPlayer = new MultiPlayer();
        String path = "http://f3.xiami.net/4/102/97302/467937/08_1770512257_2715148.mp3";
        String local = "/sdcard/music/Ina-fall.mp3";
        //mPlayer.setDataSourceAsync(path);
        mPlayer.setDataSource(path);
        mPlayer.start();
        
        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName());
        //mWakeLock.setReferenceCounted(false);        
	}

    public IBinder onBind(Intent intent) {
        mServiceInUse = true;
        return mBinder;
    }	
	   /**
     * Provides a unified interface for dealing with midi files and
     * other media files.
     */
    private class MultiPlayer {
        private MediaPlayer mMediaPlayer = new MediaPlayer();
        private Handler mHandler;
        private boolean mIsInitialized = false;

        public MultiPlayer() {
            mMediaPlayer.setWakeMode(MediaPlaybackService.this, PowerManager.PARTIAL_WAKE_LOCK);
        }

        public void setDataSourceAsync(String path) {
            try {
                mMediaPlayer.reset();
                mMediaPlayer.setDataSource(path);
                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mMediaPlayer.setOnPreparedListener(preparedlistener);
                mMediaPlayer.prepareAsync();
            } catch (IOException ex) {
                // TODO: notify the user why the file couldn't be opened
                mIsInitialized = false;
                return;
            } catch (IllegalArgumentException ex) {
                // TODO: notify the user why the file couldn't be opened
                mIsInitialized = false;
                return;
            }
            mMediaPlayer.setOnCompletionListener(listener);
            mMediaPlayer.setOnErrorListener(errorListener);
            
            mIsInitialized = true;
        }
        
        public void setDataSource(String path) {
            try {
                mMediaPlayer.reset();
                mMediaPlayer.setOnPreparedListener(null);
                if (path.startsWith("content://")) {
                    mMediaPlayer.setDataSource(MediaPlaybackService.this, Uri.parse(path));
                } else {
                    mMediaPlayer.setDataSource(path);
                }
                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mMediaPlayer.prepare();
            } catch (IOException ex) {
                // TODO: notify the user why the file couldn't be opened
                mIsInitialized = false;
                return;
            } catch (IllegalArgumentException ex) {
                // TODO: notify the user why the file couldn't be opened
                mIsInitialized = false;
                return;
            }
            mMediaPlayer.setOnCompletionListener(listener);
            mMediaPlayer.setOnErrorListener(errorListener);
            
            mIsInitialized = true;
        }
        
        public boolean isInitialized() {
            return mIsInitialized;
        }

        public void start() {
            Logger.d("MultiPlayer.start called");
            mMediaPlayer.start();
        }

        public void stop() {
            mMediaPlayer.reset();
            mIsInitialized = false;
        }

        /**
         * You CANNOT use this player anymore after calling release()
         */
        public void release() {
            stop();
            mMediaPlayer.release();
        }
        
        public void pause() {
            mMediaPlayer.pause();
        }
        
        public void setHandler(Handler handler) {
            mHandler = handler;
        }

        MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() {
            public void onCompletion(MediaPlayer mp) {
                // Acquire a temporary wakelock, since when we return from
                // this callback the MediaPlayer will release its wakelock
                // and allow the device to go to sleep.
                // This temporary wakelock is released when the RELEASE_WAKELOCK
                // message is processed, but just in case, put a timeout on it.
                mWakeLock.acquire(30000);
                mHandler.sendEmptyMessage(TRACK_ENDED);
                mHandler.sendEmptyMessage(RELEASE_WAKELOCK);
            }
        };

        MediaPlayer.OnPreparedListener preparedlistener = new MediaPlayer.OnPreparedListener() {
            public void onPrepared(MediaPlayer mp) {
                notifyChange(ASYNC_OPEN_COMPLETE);
            }
        };
 
        MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
            public boolean onError(MediaPlayer mp, int what, int extra) {
                switch (what) {
                case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
                    mIsInitialized = false;
                    mMediaPlayer.release();
                    // Creating a new MediaPlayer and settings its wakemode does not
                    // require the media service, so it's OK to do this now, while the
                    // service is still being restarted
                    mMediaPlayer = new MediaPlayer(); 
                    mMediaPlayer.setWakeMode(MediaPlaybackService.this, PowerManager.PARTIAL_WAKE_LOCK);
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(SERVER_DIED), 2000);
                    return true;
                default:
                    Logger.d("Error: " + what + "," + extra);
                    break;
                }
                return false;
           }
        };

        public long duration() {
            return mMediaPlayer.getDuration();
        }

        public long position() {
            return mMediaPlayer.getCurrentPosition();
        }

        public long seek(long whereto) {
            mMediaPlayer.seekTo((int) whereto);
            return whereto;
        }

        public void setVolume(float vol) {
            mMediaPlayer.setVolume(vol, vol);
        }
    }
    
    private void notifyChange(String what) {
        
//        Intent i = new Intent(what);
//        i.putExtra("id", Long.valueOf(getAudioId()));
//        i.putExtra("artist", getArtistName());
//        i.putExtra("album",getAlbumName());
//        i.putExtra("track", getTrackName());
//        sendBroadcast(i);
//        
//        if (what.equals(QUEUE_CHANGED)) {
//            saveQueue(true);
//        } else {
//            saveQueue(false);
//        }
//        
//        // Share this notification directly with our widgets
//        mAppWidgetProvider.notifyChange(this, what);
    }    
    /*
     * By making this a static class with a WeakReference to the Service, we
     * ensure that the Service can be GCd even when the system process still
     * has a remote reference to the stub.
     */
    static class ServiceStub extends IMediaPlaybackService.Stub {
        WeakReference<MediaPlaybackService> mService;
        
        ServiceStub(MediaPlaybackService service) {
            mService = new WeakReference<MediaPlaybackService>(service);
        }

        public void openFile(String path) {
        	mService.get().openFile(path);
        }
        public void stop() {
            mService.get().stop();
        }
        public void pause() {
            mService.get().pause();
        }
        public void play() {
            mService.get().play();
        }
        public long position() {
            return mService.get().position();
        }
        public long duration() {
            return mService.get().duration();
        }
        public long seek(long pos) {
            return mService.get().seek(pos);
        }
        
	    public void setRepeatMode(int repeatmode) {
	    	mService.get().setRepeatMode(repeatmode);
	    }
	    
        public String getPath() {
            return mService.get().getPath();
        }
		public boolean isPlaying() {
			return mService.get().isPlaying();
		}	    
    }    
    private final IBinder mBinder = new ServiceStub(this);
}